package cn.lsh.kafka.db.service;

import cn.lsh.kafka.db.dao.OffsetMapper;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import javax.sql.DataSource;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;

public class ServiceFactory {

	private static SqlSession sqlSession;

	//私有构造器
	private ServiceFactory() {}

	private static SqlSession session() {
		TransactionFactory factory = new JdbcTransactionFactory();
		// DataSource dataSource = new PooledDataSource("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/bigdata", "root", "admin");
		DataSource dataSource = new PooledDataSource("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/traffic", "root", "admin");
		Environment environment = new Environment("ID", factory, dataSource);
		Configuration conf = new Configuration(environment);
		SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(conf);
		return sessionFactory.openSession();
	}

	public static SqlSession createSession() {
		//维持一个单例sqlSession
		if (sqlSession == null) {
			sqlSession = session();
		} else {
			try {
				Connection connection = sqlSession.getConnection();
				boolean isClose = connection.isClosed();
				if (isClose) {
					sqlSession = session();
				}
			} catch (Exception e) {
				sqlSession = session();
			}
		}
		return sqlSession;
	}

	public static void commit() {
		if (sqlSession != null) {
			sqlSession.commit();
		}
	}

	public static void close() {
		if (sqlSession != null) {
			sqlSession.close();
		}
	}

	public static void commitAndClose() {
		commit();
		close();
	}

	public static <T> T buildService(Class<T> clazz) {
		try {
			String name = clazz.getName();
			String implName = name.replaceAll(clazz.getSimpleName(), "impl.") + clazz.getSimpleName() + "Impl";
			//反射加载service的实现类
			Class<?> implClass = clazz.getClassLoader().loadClass(implName);
			Constructor<?> constructor = implClass.getConstructor(SqlSession.class);
			Object o = constructor.newInstance(createSession());
			String mapperName = name.replaceAll(clazz.getSimpleName(), clazz.getSimpleName().replaceAll("Service", "Mapper")).replaceAll("service", "dao");
			//反射加载Mapper类
			Class<?> mapperClass = clazz.getClassLoader().loadClass(mapperName);
			//反射调用BaseService的setMapper向SQLSession中注册Mapper
			Method setMapper = implClass.getMethod("setMapper", Class.class);
			setMapper.invoke(o, mapperClass);
			return (T) o;
		} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
			throw new RuntimeException("反射Service异常--" + e);
		}
	}
}
